#ifndef SEGMENT_H
#define SEGMENT_H

/**
 * \file	segment.h
 * \brief	Declaration de la classe Segment representant un ensemble connexe de vertex dans un maillage appartenants a la meme classe de segmentation (voir la classe \class Map, methode segment).
 */

/* ______________________________ My includes ____ */
#include "mesh.h"

/* ____________________________ STD Librairies ___ */
#include <list>

/*! \def EQUAL
  criteria of creation of a Segment : all neighbours with the same map value will constitute the segment.
 */
#define EQUAL 0

/*! \def GREATER_EQUAL
  criteria of creation of a Segment : all neighbours with a value equal or greater than the seed vertex value will constitute the segment.
 */
#define GREATER_EQUAL 1

/*! \def LESSER_EQUAL
  criteria of creation of a Segment : all neighbours with a value equal or lesser than the seed vertex value will constitute the segment.
 */
#define LESSER_EQUAL 2

using namespace std;

class Segment
{
	/*!
	 * \class Segment
	 * \brief Classe représentant une zone connexe d'un maillage dont tous les vertex partagent une propriete vis-a-vis de leur valeur dans une map.
	 * 
	 * Classe représentant une zone connexe d'un maillage dont tous les vertex partagent une propriete vis-a-vis de leur valeur dans une map :
	 * Exemples :
	 * - tous les vertex de la zone ont une valeur inferieure a un seuil.
	 * - tous les vertex de la zone ont la meme valeur.
	 * - ...
	 *
	 * The creation of a segment is usually defined by a criteria AND a specific vertex on a given mesh we will call the "seed".
	 * 
	 * Des methodes peuvent etre ajoutees pour creer des segments selon d'autres proprietes que celles presntes.
	 * D'autres critere de reation de zone peuvent aussi etre ajoutes par la suite selon les besoins des utilisateurs.
	 * Exemples :
	 * - Un vertex appartient au segment si la distance euclidienne entre lui et le segment est plus petite qu'un seuil.
	 *   Ce qui engendrerait une zone a l'interieur de laquelle tous les vertex seraient proches les uns des autres (selon le seuil).
	 * - Idem selon des criteres d'aires, de couleur, de deplacements...
	 * - ...
	 *
	 */
	
	private :
		int				id;			/*! Every segment is given an ID which should be unique (This attribute is automatically set at the creation of the object).*/
		double			depth;		/*! Every segment is given a depth according to a map.*/
		list<Vertex*>	verts;		/*! A list containing a pointer to every vertex contained in the segment.*/
		
		static int		counter;	/*! <This static variable will contain at every time the number of segment that has been created since the begening of the program.*/
		
	public:
		/*!
		*  \brief Default constructor of the Segment class.
		*
		*  Default constructor of the Segment class : Every attributes are initialized to 0 (int,float,double,...) NULL (pointers) or are cleared (lists, stacks, ...).
		*/
		Segment();
		
		/*!
		*  \brief Copy constructor of the Segment class.
		*
		*  Copy constructor of the Segment class.
		*/
		Segment ( const Segment& _s );
		
		/*!
		*  \brief Destructor of the Segment class.
		*
		*  Destructor of the Segment class.
		*/
		~Segment();
		
		/*!
		*  \brief Affectation operator of the Segment class.
		*
		*  Affectation operator of the Segment class.
		*/
		Segment& operator= ( const Segment& _s );
		
		/*!
		*  \brief Addition operator of the Segment class.
		*
		*  Addition operator of the Segment class.
		*/
		Segment& operator+ ( const Segment& _s );
		
		/*!
		*  \brief Addition operator of the Segment class.
		*
		*  Addition operator of the Segment class.
		*/
		Segment& operator+ ( const Segment*& _s );
		
		/*!
		*  \brief Self addition operator of the Segment class.
		*
		*  Self addition operator of the Segment class.
		*/
		Segment& operator+= ( const Segment& _s );
		
		/*!
		*  \brief Self addition operator of the Segment class.
		*
		*  Self addition operator of the Segment class.
		*/
		Segment& operator+= ( const Segment*& _s );
		
		/*!
		*  \brief Getter of the Segment class.
		*
		*  Getter of the Segment class.
		*
		*  \return (int) Returns the ID of the Segment.
		*/
		int getID ();
		
		/*!
		*  \brief Getter of the Segment class.
		*
		*  Getter of the Segment class.
		*
		*  \return (int) Returns the depth of the Segment.
		*/
		double getDepth ();
		
		/*!
		*  \brief Getter of the Segment class.
		*
		*  Getter of the Segment class.
		*
		*  \return (int) Returns the color of the Segment.
		*/
		Vector3D getColor ();
		
		/*!
		*  \brief Getter of the Segment class.
		*
		*  Getter of the Segment class.
		*
		*  \return (int) Returns the color of the Segment in a double[3] array.
		*/
		double* getColorArray ();
		
		/*!
		*  \brief Getter of the Segment class.
		*
		*  Getter of the Segment class.
		*
		*  \return (int) Returns a list containing each vertex that is a part of the Segment.
		*/
		list<Vertex*> getVerts ();
		
		/*!
		*  \brief Setter of the Segment class.
		*
		*  Setter of the Segment class.
		*
		*  \param _ID : ID to attribute to the segment.
		*
		*  \return (void)
		*/
		void setID ( int _ID );
		
		/*!
		*  \brief Setter of the Segment class.
		*
		*  Setter of the Segment class.
		*
		*  \param _depth : Depth to attribute to the segment.
		*
		*  \return (void)
		*/
		void setDepth ( double _depth );
		
		/*!
		*  \brief Setter of the Segment class.
		*
		*  Setter of the Segment class.
		*
		*  \param _color : Color to attribute to the segment.
		*
		*  \return (void)
		*/
		void setColor ( Vector3D _color );
		
		/*!
		*  \brief Setter of the Segment class.
		*
		*  Setter of the Segment class.
		*
		*  \param _v : list of vertex containing each vertex of the segment.
		*
		*  \return (void)
		*/
		void setVerts ( list<Vertex*> _v );
		
		/*!
		*  \brief Computes the boundary of a segment.
		*
		*  Computes the boundary of a segment.
		*
		*  \return (list<Vertex*>) Returns a list of all the vertices componing the segment's boundary.
		*/
		list<Vertex*> getBoundary ();
		
		/*!
		*  \brief Computes the boundary of a segment and mark the vertices of the boundary in the _mark tab.
		*
		*  Computes the boundary of a segment and mark the vertices of the boundary in the _mark tab as 0 :
		*  This method is used by the SegmentTree::getMatchByDistance method.
		*
		*  \return (list<Vertex*>) Returns a list of all the vertices componing the segment's boundary.
		*/
		list<Vertex*> getBoundary ( int* _mark );
		
		/*!
		*  \brief Calculates the area of a segment.
		*
		*  Calculates the area of a segment.
		*  \warning Only works if the mesh is triangulated.
		*
		*  \param _mesh : Mesh supporting the segment.
		*
		*  \return (double) Returns the area of the segment.
		*/
		double getTriangulatedArea ( Mesh _mesh );
		
		/*!
		*  \brief Calculates the area of a segment.
		*
		*  Calculates the area of a segment.
		*  \warning Only works if the mesh is triangulated.
		*
		*  \param _mesh : Mesh supporting the segment.
		*
		*  \return (double) Returns the area of the segment.
		*/
		double getTriangulatedArea ( Mesh* _mesh );
		
		/*!
		*  \brief Calculates the area of a segment converted in a percentage of an other area.
		*
		*  Calculates the area of a segment converted in a percentage of an other area.
		*  \warning Only works if the mesh is triangulated.
		*
		*  \param _mesh : Mesh supporting the segment.
		*  \param _areaMesh : Area representing the 100%
		*
		*  \return (double) Returns the area of the segment converted in a percentage of the area given in parameter.
		*/
		double getTriangulatedAreaConverted ( Mesh _mesh, double _areaMesh );
		
		/*!
		*  \brief Calculates the area of a segment converted in a percentage of an other area.
		*
		*  Calculates the area of a segment converted in a percentage of an other area.
		*  \warning Only works if the mesh is triangulated.
		*
		*  \param _mesh : Mesh supporting the segment.
		*  \param _areaMesh : Area representing the 100%
		*
		*  \return (double) Returns the area of the segment converted in a percentage of the area given in parameter.
		*/
		double getTriangulatedAreaConverted ( Mesh* _mesh, double _areaMesh );
		
		/*!
		*  \brief Gets the begining of the vertices list of the segment.
		*
		*  Gets the begining of the vertices list of the segment.
		*
		*  \return (list<Vertex*>::iterator) Returns an iterator to the begining of the list.
		*/
		list<Vertex*>::iterator getBegin();
		
		/*!
		*  \brief Gets the end of the vertices list of the segment.
		*
		*  Gets the end of the vertices list of the segment.
		*
		*  \return (list<Vertex*>::iterator) Returns an iterator to the end of the list.
		*/
		list<Vertex*>::iterator getEnd();
		
		/*!
		*  \brief Clears a segment.
		*
		*  Clears a segment;
		*
		*  \return (void)
		*/
		void clear ();
		
		/*!
		*  \brief Adds a vertex to the Segment.
		*
		*  Adds a vertex to the Segment.
		*
		*  \param _v : Vertex to add to the segment.
		*
		*  \return (void)
		*/
		void addVert ( Vertex* _v );
		
		/*!
		*  \brief Adds a segment to the Segment.
		*
		*  Adds a segment to the Segment.
		*
		*  \param _s : Segment to add to the segment.
		*
		*  \return (void)
		*/
		void addSegment ( Segment* _s );
		
		/*!
		*  \brief Removes a vertex of the Segment.
		*
		*  Removes a vertex of the Segment.
		*  If this vertex is not a part of the segment this methods does nothing.
		*
		*  \param _v : Vertex to remove.
		*
		*  \return (void)
		*/
		void removeVert ( Vertex* _v );
		
		/*!
		*  \brief Creates a segment within the "equal value" criteria.
		*
		*  Creates a segment within the "equal value" criteria :
		*  Every vertex with the same value than the seed value and which is a part of the segment neighbour will be added to the Segment.
		*
		*  \param _seed : "seed" vertex : the segment to create will grown from this vertex.
		*  \param _mesh : The mesh containing the seed vertex. Essential to get the neighbourhood informations.
		*  \param _map : map describing the vertices values.
		*
		*  \ref explanationsaboutthesegmentscreation "See an illustration of segments creation."
		*
		*  \return (void)
		*
		*  \todo il faudra penser pourquoi pas a ajouter un attribut feature a chaque vertex. Cela evitera de passer une map en parametre de cette methode.
		*/
		void createFromSeed_Eq ( Vertex* _seed, Mesh _mesh, Map _map );
		
		/*!
		*  \brief Creates a segment within the "equal value" criteria AND set the corresponding mark of each vertices of the segment to the segment's depth.
		*
		*  Creates a segment within the "equal value" criteria AND set the corresponding mark of each vertices of the segment to the segment's depth :
		*  Every vertex with the same value than the seed value and which is a part of the segment neighbour will be added to the Segment.
		*
		*  \param _seed : "seed" vertex : the segment to create will grown from this vertex.
		*  \param _mesh : The mesh containing the seed vertex. Essential to get the neighbourhood informations.
		*  \param _map : map describing the vertices values.
		*
		*  \ref explanationsaboutthesegmentscreation "See an illustration of segments creation."
		*
		*  \return (void)
		*
		*  \todo il faudra penser pourquoi pas a ajouter un attribut feature a chaque vertex. Cela evitera de passer une map en parametre de cette methode.
		*/
		void createFromSeed_Eq ( Vertex* _seed, Mesh _mesh, Map _map, int* _mark );
		
		/*!
		*  \brief Creates a segment within the "Greater or equal value" criteria.
		*
		*  Creates a segment within the "Greater or equal than value" criteria :
		*  Every vertex with the same value or a greater value than the seed value and which is a part of the segment neighbour will be added to the Segment.
		*
		*
		*  \param _seed : "seed" vertex : the segment to create will grown from this vertex.
		*  \param _mesh : The mesh containing the seed vertex. Essential to get the neighbourhood informations.
		*  \param _map : map describing the vertices values.
		*
		*  \ref explanationsaboutthesegmentscreation "See an illustration of segments creation."
		*
		*  \return (void)
		*/
		void createFromSeed_GrEq ( Vertex* _seed, Mesh _mesh, Map _map );
		
		/*!
		*  \brief Creates a segment within the "Greater or equal value" criteria AND set the corresponding mark of each vertices of the segment to the segment's depth.
		*
		*  Creates a segment within the "Greater or equal than value" criteria AND set the corresponding mark of each vertices of the segment to the segment's depth. :
		*  Every vertex with the same value or a greater value than the seed value and which is a part of the segment neighbour will be added to the Segment.
		*
		*
		*  \param _seed : "seed" vertex : the segment to create will grown from this vertex.
		*  \param _mesh : The mesh containing the seed vertex. Essential to get the neighbourhood informations.
		*  \param _map : map describing the vertices values.
		*
		*  \ref explanationsaboutthesegmentscreation "See an illustration of segments creation."
		*
		*  \return (void)
		*/
		void createFromSeed_GrEq ( Vertex* _seed, Mesh _mesh, Map _map, int* _mark );
		
		/*!
		*  \brief Creates a segment within the "Lesser or equal value" criteria.
		*
		*  Creates a segment within the "Lesser or equal value" criteria :
		*  Every vertex with the same value or a lesser value than the seed value and which is a part of the segment neighbour will be added to the Segment.
		*
		*
		*  \param _seed : "seed" vertex : the segment to create will grown from this vertex.
		*  \param _mesh : The mesh containing the seed vertex. Essential to get the neighbourhood informations.
		*  \param _map : map describing the vertices values.
		*
		*  \ref explanationsaboutthesegmentscreation "See an illustration of segments creation."
		*
		*  \return (void)
		*/
		void createFromSeed_LeEq ( Vertex* _seed, Mesh _mesh, Map _map );
		
		/*!
		*  \brief Creates a segment within the "Lesser or equal value" criteria AND set the corresponding mark of each vertices of the segment to the segment's depth.
		*
		*  Creates a segment within the "Lesser or equal value" criteria AND set the corresponding mark of each vertices of the segment to the segment's depth.
		*
		*  \param _seed : "seed" vertex : the segment to create will grown from this vertex.
		*  \param _mesh : The mesh containing the seed vertex. Essential to get the neighbourhood informations.
		*  \param _map : map describing the vertices values.
		*  \param _mark : array of mark we want to modify in this method.
		*
		*  \ref explanationsaboutthesegmentscreation "See an illustration of segments creation."
		*
		*  \return (void)
		*/
		void createFromSeed_LeEq ( Vertex* _seed, Mesh _mesh, Map _map, int* _mark );
		
		/*!
		*  \brief Creates a segment within a specific criteria.
		*
		*  Creates a segment within a specific criteria.
		*
		*
		*  \param _criteria : criteria of segment creation. Can be set as EQUAL, GREATER_EQUAL or LESSER_EQUAL.
		*  \param _seed : "seed" vertex : the segment to create will grown from this vertex.
		*  \param _mesh : The mesh containing the seed vertex. Essential to get the neighbourhood informations.
		*  \param _map : map describing the vertices values.
		*
		*  \ref explanationsaboutthesegmentscreation "See an illustration of segments creation."
		*
		*  \return (void)
		*/
		void createFromSeed ( int _criteria, Vertex* _seed, Mesh _mesh, Map _map );
		
		/*!
		*  \brief Notice whether or not a vertex is contained in the segment.
		*
		*  Notice whether or not a given vertex is contained in the segment.
		*
		*  \param _v : Vertex we want to know if it is contained in the Segment.
		*
		*  \return (bool) Return true if the segment contains _v, false else.
		*/
		bool contains ( Vertex* _v );
		
		/*!
		*  \brief Notice whether or not a vertex ID is contained in the segment.
		*
		*  Notice whether or not a given vertex ID is contained in the segment.
		*
		*  \param _vertID : ID of the vertex we want to know if it is contained in the Segment.
		*
		*  \return (bool) Return true if the segment contains a vertex of ID _vertID, false else.
		*/
		bool contains ( int _vertID );
		
		/*!
		*  \brief Notice whether or not a segment is contained in the segment.
		*
		*  Notice whether or not a given segment is contained in the segment.
		*
		*  \param _s : Segment we want to know if it is contained in the Segment.
		*
		*  \return (bool) Return true if the segment contains _s, false else.
		*/
		bool contains ( Segment _s );

		/*!
		*  \brief Notice whether or not a segment is contained in the segment.
		*
		*  Notice whether or not a given segment is contained in the segment.
		*
		*  \param _s : Segment we want to know if it is contained in the Segment.
		*
		*  \return (bool) Return true if the segment contains _s, false else.
		*/
		bool contains(Segment* _s);
		
		/*!
		*  \brief Notfies whether or not a segment intersects the calling segment.
		*
		*  Notfies whether or not a segment intersects the calling segment.
		*
		*  \param _s : Segment we want to know if it intersects with the calling segment.
		*
		*  \return (bool) Return true if the segment intersects _s, false else.
		*/
		bool intersects ( Segment _s );
		
		/*!
		*  \brief Notfies whether or not a segment intersects the calling segment.
		*
		*  Notfies whether or not a segment intersects the calling segment.
		*
		*  \param _s : Segment we want to know if it intersects with the calling segment.
		*
		*  \return (bool) Return true if the segment intersects _s, false else.
		*/
		bool intersects ( Segment* _s );
		
		/*!
		*  \brief Notfies whether or not a segment intersects the calling segment and how big is the intersection.
		*
		*  Notfies whether or not a segment intersects the calling segment and how big is the intersection.
		*
		*  \param _s : Segment we want to know if it intersects with the calling segment.
		*
		*  \return (int) Returns the number of vertices in the intersection between the two segments.
		*/
		int intersectsQuantity ( Segment _s );
		
		/*!
		*  \brief Notfies whether or not a segment intersects the calling segment and how big is the intersection.
		*
		*  Notfies whether or not a segment intersects the calling segment and how big is the intersection.
		*
		*  \param _s : Segment we want to know if it intersects with the calling segment.
		*
		*  \return (int) Returns the number of vertices in the intersection between the two segments.
		*/
		int intersectsQuantity ( Segment* _s );
		
		/*!
		*  \brief Dilates a segment based on an edge distance (extends it).
		*
		*  Dilates a segment based on an edge distance.
		*
		*  \param _size : Edge distance to enlarge the segment.
		*
		*  \return (void)
		*/
		void morphologicalDilatation ( Mesh _mesh, int _size );
		
		/*!
		*  \brief Overload of the morphologicalDilatation method.
		*/
		void morphologicalDilatation ( Mesh* _mesh, int _size );
		
		/*!
		*  \brief Erode a segment based on an edge distance (diminishes it).
		*
		*  Erode a segment based on an edge distance.
		*
		*  \param _size : Edge distance to reduce the segment.
		*
		*  \return (void)
		*/
		void morphologicalErosion ( Mesh _mesh, int _size );
		
		/*!
		*  \brief Overload of the morphologicalErosion method.
		*/
		void morphologicalErosion ( Mesh* _mesh, int _size );
		
		/*!
		*  \brief Applies an opening operation on the segment.
		*
		*  Applies an opening operation on the segment :
		*  One erosion followed by one dilatation with the same size.
		*
		*  \param _size : Size of the erosion/dilatation
		*
		*  \return (void)
		*/
		void morphologicalOpening ( Mesh _mesh, int _size );
		
		/*!
		*  \brief Overload of the opening method.
		*/
		void morphologicalOpening ( Mesh* _mesh, int _size );
		
		/*!
		*  \brief Applies a closing operation on the segment.
		*
		*  Applies a closing operation on the segment.
		*  One dilatation followed by one erosion with the same size.
		*
		*  \param _size : Size of the erosion/dilatation
		*
		*  \return (void)
		*/
		void morphologicalClosing ( Mesh _mesh, int _size );
		
		/*!
		*  \brief Overload of the closing method.
		*/
		void morphologicalClosing ( Mesh* _mesh, int _size );
		
//		/*!
//		*  \brief This is to know if there is some other segments around the calling one, and if there are some to know them.
//		*
//		*  This is to know if there is some other segments around the calling one, and if there are some to know them.
//		*
//		*  \param _mesh : Mesh supporting the segments.
//		*  \param _distMax : Distance maximum for a segment to be considered as a neighbour of the calling one.
//		*
//		*  \return (lis<Segment*>) Returns a list containing all the segments that are neighbours of the calling one.
//		*/
//		list<Segment*> getNeighbours ( Mesh* _mesh, int _distMax );
		
		/*!
		*  \brief Displays the vertices contained in a Segment.
		*
		*  Displays the vertices contained in a Segment.
		*
		*  \param _r : Red component of the color to display.
		*  \param _g : Green component of the color to display.
		*  \param _b : Blue component of the color to display.
		*
		*  \return (void)
		*/
		void displayVertices ( float _r, float _g, float _b );
		
		/*!
		*  \brief Displays the vertices contained in a Segment.
		*
		*  Displays the vertices contained in a Segment.
		*
		*  \return (void)
		*/
		void displayVertices ();
		
		/*!
		*  \brief Displays the edges contained in a Segment.
		*
		*  Displays the edges contained in a Segment.
		*  To make this methode faster, we can suppres the test of owning of boths vertices of the edge to the segment.
		*  This will be faster but some edges with an extremity which is not a part of the segment would be drawed;
		*
		*  \param _r : Red component of the color to display.
		*  \param _g : Green component of the color to display.
		*  \param _b : Blue component of the color to display.
		*
		*  \return (void)
		*/
		void displayEdges ( float _r, float _g, float _b );
		
		/*!
		*  \brief Displays the edges contained in a Segment.
		*
		*  Displays the edges contained in a Segment.
		*  To make this methode faster, we can suppres the test of owning of boths vertices of the edge to the segment.
		*  This will be faster but some edges with an extremity which is not a part of the segment would be drawed;
		*
		*  \return (void)
		*/
		void displayEdges ();
		
		/*!
		*  \brief Displays the faces contained in a Segment.
		*
		*  Displays the faces contained in a Segment :
		*  Every face containing at least one vertex of the segment is diaplyed.
		*
		*  \param _r : Red component of the color to display.
		*  \param _g : Green component of the color to display.
		*  \param _b : Blue component of the color to display.
		*
		*  \return (void)
		*/
		void displayFaces ( float _r, float _g, float _b );
		
		/*!
		*  \brief Displays the faces contained in a Segment.
		*
		*  Displays the faces contained in a Segment.
		*  Every face containing at least one vertex of the segment is diaplyed.
		*
		*  \return (void)
		*/
		void displayFaces ();
		
		/*!
		*  \brief Displays the Segment in a selected mode.
		*
		*  Displays the Segment in a selected mode.
		*
		*  \param _mode : mode to display the Segment. Can be set to VERTICES, EDGES or FACES.
		*  \param _r : Red component of the color to display.
		*  \param _g : Green component of the color to display.
		*  \param _b : Blue component of the color to display.
		*
		*  \return (void)
		*/
		void display ( int _mode, float _r, float _g, float _b );
		
		/*!
		*  \brief Displays the Segment in a selected mode.
		*
		*  Displays the Segment in a selected mode.
		*
		*  \param _mode : mode to display the Segment. Can be set to VERTICES, EDGES or FACES.
		*
		*  \return (void)
		*/
		void display ( int _mode=FACES );
};

#endif
